package com.strato.mybatis.generator.v1_2_0.ui;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.CommentGeneratorConfiguration;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.JDBCConnectionConfiguration;
import org.mybatis.generator.config.JavaClientGeneratorConfiguration;
import org.mybatis.generator.config.JavaModelGeneratorConfiguration;
import org.mybatis.generator.config.JavaTypeResolverConfiguration;
import org.mybatis.generator.config.ModelType;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.config.SqlMapGeneratorConfiguration;
import org.mybatis.generator.config.TableConfiguration;
import org.mybatis.generator.internal.DefaultShellCallback;

import com.strato.mybatis.generator.v1_2_0.config.GenerateConfig;
import com.strato.mybatis.generator.v1_2_0.ui.ext.StratoCommentGenerator;

public class GeneratorUtil {
	public static void configuration(Map<String,String> configMap,List<Map<String,String>> tableMapList) throws Exception{
		List<String> warnings = new ArrayList<String>();
		boolean overwrite = true;
		Properties prop = GenerateConfig.getInstance().getProperties();
		Configuration config = new Configuration();
		Context context = new Context(ModelType.CONDITIONAL);
		
		CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration();
		commentGeneratorConfiguration.setConfigurationType(StratoCommentGenerator.class.getName());
		commentGeneratorConfiguration.addProperty("suppressAllComments", 
				prop.getProperty("attribute.commentGenerator.suppressAllComments"));
		commentGeneratorConfiguration.addProperty("addRemarkComments", 
				prop.getProperty("attribute.commentGenerator.addRemarkComments"));
		
		commentGeneratorConfiguration.addProperty("suppressDate", 
				prop.getProperty("attribute.commentGenerator.suppressDate"));
		context.setCommentGeneratorConfiguration(commentGeneratorConfiguration);
		
		JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
		jdbcConnectionConfiguration.setConnectionURL(configMap.get("jdbcUrl"));
		jdbcConnectionConfiguration.setDriverClass(configMap.get("driver"));
		jdbcConnectionConfiguration.setPassword(configMap.get("password"));
		jdbcConnectionConfiguration.setUserId(configMap.get("userId"));
		context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);
		
		JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration();
		javaTypeResolverConfiguration.addProperty("forceBigDecimals",
				prop.getProperty("attribute.javaTypeResolver.forceBigDecimals"));
		context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration);
		new File(configMap.get("targetModel")).mkdirs();
		new File(configMap.get("targetXML")).mkdirs();
		new File(configMap.get("targetMapper")).mkdirs();
		JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
		String modelSubPackage=prop.getProperty("attribute.javaModelGenerator.modelSubPackage","");
		if(!"".equals(modelSubPackage)){
			if(!"".equals(configMap.get("targetPackage"))&&!modelSubPackage.startsWith(".")){
				modelSubPackage="."+modelSubPackage;
			}
		}
		javaModelGeneratorConfiguration.setTargetPackage(configMap.get("targetPackage")+modelSubPackage);
		javaModelGeneratorConfiguration.setTargetProject(configMap.get("targetModel"));
		javaModelGeneratorConfiguration.addProperty("enableSubPackages", 
				prop.getProperty("attribute.javaModelGenerator.enableSubPackages"));
		javaModelGeneratorConfiguration.addProperty("trimStrings",
				prop.getProperty("attribute.javaModelGenerator.trimStrings"));
		context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);
		
		String xmlSubPackage=prop.getProperty("attribute.javaModelGenerator.xmlSubPackage","");
		if(!"".equals(configMap.get("targetPackage"))&&!"".equals(xmlSubPackage)){
			if(!xmlSubPackage.startsWith(".")){
				xmlSubPackage="."+xmlSubPackage;
			}
		}
		SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
		sqlMapGeneratorConfiguration.setTargetPackage(configMap.get("targetPackage")+xmlSubPackage);
		sqlMapGeneratorConfiguration.setTargetProject(configMap.get("targetXML"));
		sqlMapGeneratorConfiguration.addProperty("enableSubPackages",
				prop.getProperty("attribute.sqlMapGenerator.enableSubPackages"));
		context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);
		
		String mapperSubPackage=prop.getProperty("attribute.javaModelGenerator.mapperSubPackage","");
		if(!"".equals(configMap.get("targetPackage"))&&!"".equals(mapperSubPackage)){
			if(!mapperSubPackage.startsWith(".")){
				mapperSubPackage="."+mapperSubPackage;
			}
		}
		JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
		javaClientGeneratorConfiguration.setTargetPackage(configMap.get("targetPackage")+mapperSubPackage);
		javaClientGeneratorConfiguration.setTargetProject(configMap.get("targetMapper"));
		javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");//
		//javaClientGeneratorConfiguration.setConfigurationType("MIXEDMAPPER:XML");
		javaClientGeneratorConfiguration.addProperty("enableSubPackages",
				prop.getProperty("attribute.javaClientGenerator.enableSubPackages"));
		context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
										
		String sGenerateExampleClass=prop.getProperty("attribute.javaModelGenerator.generateExampleClass","true");
		boolean generateExample=Boolean.parseBoolean(sGenerateExampleClass);
		for(Map<String,String> tableMap : tableMapList){
			TableConfiguration tc = new TableConfiguration(context);
			tc.setDomainObjectName(tableMap.get("tableDomainName"));
			tc.setTableName(tableMap.get("tableName"));
			tc.setCountByExampleStatementEnabled(generateExample);
			tc.setDeleteByExampleStatementEnabled(generateExample);
			tc.setDeleteByPrimaryKeyStatementEnabled(true);
			tc.setInsertStatementEnabled(true);
			tc.setSelectByPrimaryKeyStatementEnabled(true);
			tc.setUpdateByPrimaryKeyStatementEnabled(true);
			tc.setSelectByExampleStatementEnabled(generateExample);
			tc.setUpdateByExampleStatementEnabled(generateExample);
			tc.setSelectByExampleQueryId("true");
			tc.addProperty(PropertyRegistry.TABLE_USE_ACTUAL_COLUMN_NAMES, prop.getProperty("attribute.tableConfiguration."+PropertyRegistry.TABLE_USE_ACTUAL_COLUMN_NAMES));
			context.addTableConfiguration(tc);
		}
		
		context.setTargetRuntime("MyBatis3");
		context.setId("stratoUIGenerateoTOMybatis");
		config.addContext(context);
		{//output to file
			String userDir = System.getProperty("user.dir");
			File generatedDir=new File(userDir+"/.generated");
			generatedDir.mkdirs();
			String dbName=configMap.get("dbName");
			String filename=dbName+".xml";
			File configFile=new File(generatedDir,filename);
			FileWriter writer=new FileWriter(configFile);
			try{
				writer.write(config.toDocument().getFormattedContent());
			}finally{
				writer.close();
			}
		}
		DefaultShellCallback callback = new DefaultShellCallback(overwrite);
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		myBatisGenerator.generate(null);
		String generateMapperAnnoationAttr=prop.getProperty("attribute.strato.generateMybatisMapperAnnotation");
		if("true".equalsIgnoreCase(generateMapperAnnoationAttr)){
			String targetMapper=configMap.get("targetMapper");
			String fullMapperPackage=configMap.get("targetPackage")+mapperSubPackage;
			File dir=new File(targetMapper+"/"+fullMapperPackage.replaceAll("\\.", "/"));
			for(Map<String,String> tableMap : tableMapList){
				String className=tableMap.get("tableDomainName");
				File file=new File(dir,className+"Mapper.java");
				generateMapperAnnotation(file);
			}
		}
	}

	private static void generateMapperAnnotation(File file) throws IOException {
		BufferedReader r=new BufferedReader(new FileReader(file));
		StringBuffer code=new StringBuffer();
		String s=null;
		while((s=r.readLine())!=null){
			code.append(s).append("\n\r");
		}
		r.close();
		{
			int position=code.indexOf("public interface");
			code.insert(position, "@com.strato.orm.mybatis.v1_0_0.annotation.MybatisMapper\n");
		}
		BufferedWriter w=new BufferedWriter(new FileWriter(file));
		w.write(code.toString());
		w.flush();
		w.close();
	}
}
